import bean.KnnNode;

import java.util.ArrayList;

/**
 * 算法核心思想：
 * 寻找与目标最近的K个个体
 * 在定位用例中，用户所在位置的所有AP数据平均值作为一个文本；
 * 将该文本与所收集到的位置点RSSI文本集进行比较，推测最接近的位置为用户位置
 */
public class KnnTest {

    //将指纹地图存储进location数组中
    private static double location[][] =
            {{1.11,0.17},{1.11,1.24},{1.11,2.27},{1.10,3.30},{1.10,4.33},
            {1.10,5.56},{1.09,6.59},{1.07,7.73},{1.06,8.76},{1.06,9.77},
            {2.05,0.17},{2.05,1.24},{2.05,2.27},{2.04,3.30},{2.04,4.33},
            {2.03,5.56},{2.03,6.59},{2.01,7.73},{2.01,8.76},{2.01,9.77},
            {2.99,0.17},{2.99,1.23},{2.99,2.27},{2.99,3.30},{2.99,4.33},
            {2.99,5.56},{2.29,6.59},{2.99,7.73},{2.99,8.76},{2.99,9.77},
            {3.93,0.17},{3.91,1.23},{3.93,2.27},{3.93,3.30},{3.93,4.33},
            {3.93,5.56},{3.93,6.59},{3.93,7.73},{3.93,8.76},{3.93,9.77},
            {4.89,0.17},{4.89,1.23},{4.89,2.27},{4.89,3.30},{4.89,4.33},
            {4.89,5.56},{4.89,6.59},{4.89,7.73},{4.89,8.76},{4.89,9.77}};

    //各个指纹点的AP设备的RSSI平均数值
    private static int apRssi[][] =
                    {{-81,-76,-74,-71,-81,-74,-74,-71,-77,-76},
                    {-83,-75,-65,-74,-75,-84,-76,-70,-81,-81},
                    {-79,-82,-69,-80,-80,-84,-78,-71,-74,-79},
                    {-80,-80,-70,-76,-81,-80,-70,-72,-74,-76},
                    {-81,-68,-76,-75,-78,-69,-68,-72,-72,-79},
                    {-80,-73,-80,-77,-77,-72,-69,-79,-79,-77},
                    {-79,-70,-84,-81,-79,-63,-78,-79,-76,-76},
                    {-73,-70,-80,-79,-73,-64,-78,-81,-77,-70},
                    {-77,-65,-87,-84,-81,-63,-82,-82,-77,-61},
                    {-85,-75,-85,-81,-76,-75,-87,-76,-73,-75},
                    {-78,-80,-69,-70,-79,-71,-76,-69,-77,-82},
                    {-78,-82,-63,-77,-80,-80,-74,-72,-83,-82},
                    {-82,-77,-61,-74,-79,-78,-76,-68,-79,-82},
                    {-81,-78,-76,-73,-80,-81,-73,-78,-78,-82},
                    {-78,-72,-72,-74,-75,-78,-66,-72,-69,-75},
                    {-76,-63,-80,-80,-74,-76,-75,-78,-76,-74},
                    {-76,-62,-78,-77,-71,-66,-79,-66,-63,-70},
                    {-79,-71,-82,-84,-79,-73,-80,-80,-77,-71},
                    {-81,-79,-85,-86,-79,-78,-82,-85,-75,-66},
                    {-82,-75,-85,-84,-75,-76,-85,-84,-80,-74},
                    {-84,-86,-72,-73,-84,-81,-70,-79,-83,-85},
                    {-87,-75,-71,-76,-77,-82,-72,-70,-80,-84},
                    {-85,-85,-64,-68,-79,-81,-71,-69,-74,-78},
                    {-81,-85,-68,-77,-85,-78,-70,-82,-81,-78},
                    {-80,-80,-74,-74,-75,-78,-74,-69,-67,-78},
                    {-75,-65,-78,-80,-73,-78,-78,-75,-73,-77},
                    {-76,-72,-80,-78,-72,-70,-76,-74,-74,-77},
                    {-66,-75,-75,-80,-67,-68,-78,-81,-75,-69},
                    {-74,-69,-86,-82,-80,-74,-87,-80,-75,-74},
                    {-75,-73,-84,-82,-73,-76,-83,-82,-76,-75},
                    {-85,-82,-74,-68,-85,-79,-73,-84,-84,-81},
                    {-86,-79,-61,-77,-79,-77,-76,-71,-79,-85},
                    {-80,-83,-76,-74,-77,-84,-75,-72,-80,-80},
                    {-83,-79,-70,-82,-78,-80,-74,-68,-77,-80},
                    {-78,-71,-85,-74,-79,-81,-72,-71,-69,-82},
                    {-79,-71,-78,-80,-75,-81,-81,-74,-73,-77},
                    {-69,-71,-71,-77,-65,-66,-69,-77,-67,-73},
                    {-74,-62,-85,-85,-75,-73,-82,-76,-75,-72},
                    {-76,-67,-82,-77,-72,-76,-81,-79,-72,-78},
                    {-79,-79,1,1,-80,-80,-88,-86,-81,-84},
                    {-85,-81,-76,-75,-87,-78,-74,-76,-82,-82},
                    {-75,-83,-74,-80,-80,-84,-76,-74,-79,-77},
                    {-81,-76,-73,-69,-80,-79,-77,-76,-72,-78},
                    {-77,-77,-69,-71,-77,-78,-71,-75,-78,-76},
                    {-75,-76,-80,-71,-77,-76,-72,-70,-77,-82},
                    {-73,-66,-79,-72,-79,-75,-73,-66,-76,-82},
                    {-77,-63,-79,-76,-80,-73,-77,-75,-73,-78},
                    {-74,-68,-83,-78,-73,-76,-83,-77,-74,-75},
                    {-76,-65,-84,-83,-76,-79,-81,-79,-73,-79},
                    {-77,-72,-86,-84,-75,-77,-83,-83,-76,-79}};
    private static int k = 3;

    public static void execute(double[] deviceRssi) {
        int compareInt[] = new int[deviceRssi.length];
        for (int i = 0; i < deviceRssi.length; i++) {
            compareInt[i] = (int) deviceRssi[i];
        }
        ArrayList<KnnNode> close = knnPosition(compareInt, apRssi);
        double x = 0, y = 0, weight = 0;
        System.out.println("距离最近的" + k + "个点的欧氏距离为：");
        for (int i = 0; i < k; i++) {
            System.out.println("第" + close.get(i).getNum() + "号的距离：" + close.get(i).getKnnDis());
            weight = weight + close.get(i).getKnnDis();
        }
        //归一化处理
        weight = close.get(0).getKnnDis() / weight;
        for (int i = 0; i < k; i++) {
            x = x + weight * location[close.get(i).getNum()][0];
            y = y + weight * location[close.get(i).getNum()][1];
        }
        System.out.println("预测您的位置为：" + x + "," + y);
    }

    static ArrayList<KnnNode> knnPosition(int rssi[], int map[][]) {
        int n = map.length;
        ArrayList<KnnNode> distList = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            double dist = 0;
            for (int j = 0; j < 10; j++) {
                dist = dist + (rssi[j] - map[i][j]) * (rssi[j] - map[i][j]);
            }
            distList.add(new KnnNode(Math.sqrt(dist), i + 1));
        }
        distList.sort(KnnNode::compareTo);
        return distList;
    }
}
